﻿using Goway.Log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Goway.StackingUC.Modules
{
    /// <summary>
    /// 整体线程管理
    /// </summary>
    public class TaskManager
    {
        private static TaskManager taskManager = new TaskManager();

        private TaskManager() { }

        public static TaskManager GetManager() { return taskManager; }

        /// <summary>
        /// 线程池
        /// </summary>
        private Dictionary<string, Action<object>> FucOverallDic = new Dictionary<string, Action<object>>();

        /// <summary>
        /// 任务列表
        /// </summary>
        private Dictionary<string, CancellationTokenSource> TaskOverallDic =
            new Dictionary<string, CancellationTokenSource>();

        /// <summary>
        /// 添加异步运行任务
        /// </summary>
        /// <param name="name">任务名称/方法名称</param>
        /// <param name="arge">需要异步运行的委托方法</param>
        /// <returns></returns>
        public bool AddRunFunction(string name, Action<object> arge)
        {
            try
            {
                if (FucOverallDic.ContainsKey(name))
                {
                    FucOverallDic[name] = arge;
                }
                else
                {
                    FucOverallDic.Add(name, arge);
                }

                return true;
            }
            catch (Exception ex)
            {
                LoggerHelper.Error($"AddRunFunction,发生异常:{ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 添加异步运行任务
        /// </summary>
        /// <param name="name">任务名称/方法名称</param>
        /// <param name="arge">需要异步运行的委托方法</param>
        ///  <param name="arge">当前方法运行的上下文</param>
        /// <returns></returns>
        public bool AddRunFunction(string name, Action<object> arge, TaskScheduler scheduler)
        {
            try
            {
                if (FucOverallDic.ContainsKey(name))
                {
                    FucOverallDic[name] = arge;
                }
                else
                {
                    FucOverallDic.Add(name, arge);
                }

                return true;
            }
            catch (Exception ex)
            {
                LoggerHelper.Error($"AddRunFunction,发生异常:{ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 所有已添加的任务开始运行
        /// </summary>
        public void RunOverallFunction()
        {
            foreach (var item in FucOverallDic)
            {
                var tok_source = new CancellationTokenSource();
                var task = Task.Factory.StartNew(item.Value, tok_source.Token);
                task.ContinueWith(t =>
                {
                    LoggerHelper.Error($"结束线程引发的异常:{t.Exception.InnerException.Message}");

                }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted,
                    TaskScheduler.FromCurrentSynchronizationContext());

                if (TaskOverallDic.ContainsKey(item.Key))
                {
                    TaskOverallDic[item.Key] = tok_source;
                }
                else
                {
                    TaskOverallDic.Add(item.Key, tok_source);
                }
            }
        }

        /// <summary>
        /// 关闭所有任务
        /// </summary>
        internal void CloseAll()
        {
            if (FucOverallDic != null && FucOverallDic.Count > 0)
            {
                foreach (var item in FucOverallDic)
                {
                    CloseFunction(item.Key);
                }
            }
        }

        /// <summary>
        /// 启动指定任务
        /// </summary>
        /// <param name="functionName">任务名称</param>
        /// <returns>true 启动成功, false 任务已经在运行中</returns>
        public bool RunOverallFunction(string functionName)
        {
            if (FucOverallDic.ContainsKey(functionName))
            {
                var tok_source = new CancellationTokenSource();

                var function = FucOverallDic[functionName];

                var task = Task.Factory.StartNew(function, tok_source.Token);
                task.ContinueWith(t =>
                {
                    LoggerHelper.Info($"开始线程引发的异常:{t.Exception.InnerException.Message}");

                }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted,
                    TaskScheduler.FromCurrentSynchronizationContext());
                TaskOverallDic.Add(functionName, tok_source);
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 取消所有任务
        /// </summary>
        /// <returns></returns>
        public bool CloseOverallFunction()
        {
            int closeCount = 0;
            foreach (var item in TaskOverallDic)
            {
                item.Value.Cancel();
                item.Value.Token.Register(() =>
                {
                    closeCount++;
                });
            }

            bool isSuccess = closeCount == TaskOverallDic.Count();
            TaskOverallDic.Clear();
            return isSuccess;
        }

        /// <summary>
        /// 关闭指定任务
        /// </summary>
        /// <param name="functionName">方法名称/任务名称</param>
        public void CloseFunction(string functionName)
        {
            if (TaskOverallDic.ContainsKey(functionName))
            {
                TaskOverallDic[functionName].Cancel();

                TaskOverallDic[functionName].Token.Register(() =>
                {
                    LoggerHelper.Info($"方法{functionName},线程已经退出");

                    //移除指定方法
                    TaskOverallDic.Remove(functionName);
                });
            }
        }
    }

    //TODO  需要添加一个类, 放方法名称,委托任务, 以及任务当前线程环境的上下文.
}
